﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="SettingsStore.cs" company="XamlNinja">
//   2011 Richard Griffin and Ollie Riches
// </copyright>
// <summary>
//   The settings store.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace WP7Contrib.Services.Settings
{
    using System;
    using System.IO.IsolatedStorage;
    using Logging;

    /// <summary>
    /// The settings store.
    /// </summary>
    public class SettingsStore : IStoreSettings
    {
        /// <summary>
        /// The logger used to capture diagnostics information.
        /// </summary>
        private readonly ILog log;

        /// <summary>
        /// The failed to read setting.
        /// </summary>
        private const string FailedToReadSetting = "SettingsStore: Failed to read setting.";

        /// <summary>
        /// The failed to write setting.
        /// </summary>
        private const string FailedToWriteSetting = "SettingsStore: Failed to write setting.";

        /// <summary>
        /// The isolated store.
        /// </summary>
        private readonly IsolatedStorageSettings isolatedStore;

        /// <summary>
        /// Initializes a new instance of the <see cref="SettingsStore"/> class.
        /// </summary>
        public SettingsStore() : this(new DebugLog())
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SettingsStore"/> class.
        /// </summary>
        /// <param name="log">
        /// The logger used to capture diagnostics information.
        /// </param>
        public SettingsStore(ILog log)
        {
            this.log = log;
            this.isolatedStore = IsolatedStorageSettings.ApplicationSettings;
        }

        /// <summary>
        /// Attempts to read a setting value.
        /// </summary>
        /// <param name="key">
        /// The key associated with the value.
        /// </param>
        /// <param name="value">
        /// The value to be stored.
        /// </param>
        /// <typeparam name="T">The type of the value.
        /// </typeparam>
        /// <returns>
        ///  Returns true if the value was read.
        /// </returns>
        /// <exception cref="ServiceException">
        /// </exception>
        public bool TryToRead<T>(string key, out T value)
        {
            try
            {
                value = default(T);

                if (string.IsNullOrEmpty(key))
                {
                    return false;
                }

                var lowerKey = key.ToLowerInvariant();
                if (this.isolatedStore.Contains(lowerKey))
                {
                    value = this.isolatedStore[lowerKey] is T ? (T)this.isolatedStore[lowerKey] : default(T);

                    this.log.Write("SettingsStore: Read, key - '{0}', value - '{1}'", key, value);
                    return true;
                }
            }
            catch (Exception exn)
            {
                this.log.Write(FailedToReadSetting);
                throw new ServiceException(FailedToReadSetting, exn);
            }

            return false;
        }

        /// <summary>
        /// Attempts to write a setting value.
        /// </summary>
        /// <param name="key">
        /// The key associated with the value
        /// </param>
        /// <param name="value">
        /// The value to be set.
        /// </param>
        /// <typeparam name="T">The type of the value.
        /// </typeparam>
        /// <returns>
        /// Returns the instance of the store settings - fluent interface style.
        /// </returns>
        /// <exception cref="ServiceException">
        /// </exception>
        public IStoreSettings Write<T>(string key, T value)
        {
            try
            {
                var lowerKey = key.ToLowerInvariant();
                if (this.isolatedStore.Contains(lowerKey))
                {
                    this.isolatedStore[lowerKey] = value;
                }
                else
                {
                    this.isolatedStore.Add(lowerKey, value);
                }

                this.isolatedStore.Save();

                this.log.Write("SettingsStore: Write, key - '{0}', value - '{1}'", key, value);
                return this;
            }
            catch (Exception exn)
            {
                this.log.Write(FailedToWriteSetting);
                throw new ServiceException(FailedToWriteSetting, exn);
            }
        }
    }
}